/**
 * (c) E.S.A.
 */

#include <stdlib.h>
#include <pthread.h>
#include <iostream>
#include <fstream>
#include <cassert>

#include "global_data.h"
#include "connect_utilities.h"
#include "tokenizer.h"

using namespace std;

int read_from_file (char* file_name, srv_data* server)
{
	string line;
	String_Tokenizer line_tok;
	ifstream config_file(file_name);
	std::string ip, port_st;

	if (config_file.is_open())
	{
		while (! config_file.eof() )
		{
			getline (config_file,line);

			// if starts with "#" => comment
			if (line.find_first_of("#") == 0){
				continue;
			}

			line_tok.set_string(line, " \t");
			assert (line_tok.has_more_tokens());

			server->ip = line_tok.next_token();
			port_st = line_tok.next_token();				
			server->port = atoi (port_st.c_str());


		}
	}
	else{
		cout << "Unable to open file" << endl;
		return -1;
	}

	config_file.close();
	return 0;

}


void init_buffer_struct (buff_t *buffer)
{
	sem_init (&buffer->full_sem, 0, 0);
	sem_init (&buffer->empty_sem,0, CIRCULAR_BUF_SIZE);
	sem_init (&buffer->put_mutex, 0, 1);
	sem_init (&buffer->get_mutex, 0, 1);
	buffer->nextin = buffer->nextout = 0;
}


void destroy_buffer_struct (buff_t *buffer)
{
	sem_destroy (&buffer->full_sem);
	sem_destroy (&buffer->empty_sem);
	sem_destroy (&buffer->put_mutex);
	sem_destroy (&buffer->get_mutex);
	buffer->nextin = buffer->nextout = 0;
}


void init_global_data ()
{
	global.quit_flag = false;

	init_buffer_struct (&global.recv_buff);
	init_buffer_struct (&global.send_buff);

}

void add_to_send_buffer (const std::string& data)
{
	// @p: add data in send_buff
	sem_wait( &global.send_buff.empty_sem );
	sem_wait( &global.send_buff.put_mutex );

	global.send_buff.mess[global.send_buff.nextin] = data;
	global.send_buff.nextin = (global.send_buff.nextin + 1) % CIRCULAR_BUF_SIZE;

	sem_post( &global.send_buff.put_mutex );
	sem_post( &global.send_buff.full_sem );
}


int main (int argc, char* argv[])
{
	srv_data* server;
	char* file_name;
	char s[10];

	if(argc != 2) {
		cout << "SYNTAX: " << argv[0] << " config_file " << endl;
		return 0;
	}

	server = new srv_data;
	file_name = argv[1];
	if (read_from_file (file_name, server) == -1){
		return 0;
	}
	
	init_global_data ();

	cout << "server_ip = " << server->ip << " server_port = " << server->port << endl;

	// test socket communication:
	if (server->port == 6000){
		// send to 10.0.0.2 6001
		//to: <ip_address>\n body: <body_of_the_message>
		add_to_send_buffer ("to: 10.0.0.2\n body: partitia 1 data 3");
	}
	if (server->port == 6001){
		// send to 10.0.0.1 6000
		add_to_send_buffer ("to: 10.0.0.1\n body: partitia 2 data 8");
	}

	cout << "added in buffer " << global.send_buff.mess[0] << endl;
	
	// create connect_thread
	pthread_t connect_thread;
	if(pthread_create(&connect_thread, NULL, connect_main, server) != 0){
		cout << "Error: could not create server connect thread" << endl;
		delete server; return 1;
	}
	
	puts("\nPress <ENTER> to quit\n"); fflush(stdout);
	fgets(s, sizeof(s), stdin); puts("");

	global.quit_flag = true;

	// wait for join:
	if(pthread_join(connect_thread, NULL) != 0){
		cout << "Error: could not join server conn thread" << endl;
		delete server; return 1;
	}

	destroy_buffer_struct (&global.recv_buff);
	destroy_buffer_struct (&global.send_buff);

	delete server;
	return 0;
}
